package com.gitee.wsl.android.ui.spannable.span

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Paint.FontMetricsInt
import android.graphics.Rect
import android.graphics.RectF
import android.text.TextPaint
import android.text.style.ReplacementSpan
import androidx.annotation.ColorInt
import androidx.annotation.DrawableRes


/**
 * 使用ReplacementSpan在TextView中自定义Tag
 */
class TextTagSpan(private val mContext: Context, private val width: Int, private val height: Int) : ReplacementSpan() {
    private var radius = 0f
    private var leftMargin = 0
    private var rightMargin = 0
    private var strokeColor = 0
    private var strokeWidth = 0f

    @DrawableRes
    private var background = 0
    private val mTextPaint: TextPaint = TextPaint()

    init {
        mTextPaint.isAntiAlias = true
        mTextPaint.textAlign = Paint.Align.CENTER
    }

    fun setTextColor(@ColorInt textColor: Int): TextTagSpan {
        mTextPaint.color = textColor
        return this
    }

    fun setStrokeColor(@ColorInt strokeColor: Int): TextTagSpan {
        this.strokeColor = strokeColor
        return this
    }

    fun setTextSize(textSize: Float): TextTagSpan {
        mTextPaint.textSize = textSize
        return this
    }

    fun setRadius(radius: Float): TextTagSpan {
        this.radius = radius
        return this
    }

    fun setStrokeWidth(strokeWidth: Float): TextTagSpan {
        this.strokeWidth = strokeWidth
        return this
    }

    fun setLeftMargin(leftMargin: Int): TextTagSpan {
        this.leftMargin = leftMargin
        return this
    }

    fun setRightMargin(rightMargin: Int): TextTagSpan {
        this.rightMargin = rightMargin
        return this
    }

    /**
     * 设置自定义背景，如果有自定义背景，则忽略stroke。
     *
     * @param background
     * @return
     */
    fun setBackground(@DrawableRes background: Int): TextTagSpan {
        this.background = background
        return this
    }

    override fun getSize(
        paint: Paint,
        charSequence: CharSequence,
        start: Int,
        end: Int,
        fontMetricsInt: FontMetricsInt?
    ): Int {
        return width + leftMargin + rightMargin
    }

    override fun draw(
        canvas: Canvas,
        text: CharSequence,
        start: Int,
        end: Int,
        x: Float,
        top: Int,
        y: Int,
        bottom: Int,
        paint: Paint
    ) {
        canvas.save()
        val strokeRect = drawTagRect(canvas, x, y, paint)
        //drawText
        val fontMetrics = mTextPaint.fontMetricsInt
        val textCenterX = x + leftMargin + width / 2
        //baseline 计算，在strokeRect中的baseline计算，需要用到strokeRect top和height
        val textBaselineY =
            (height / 2 + (Math.abs(fontMetrics.ascent) - fontMetrics.descent) / 2 + strokeRect.top).toFloat()
        val tag = text.subSequence(start, end).toString()
        canvas.drawText(tag, textCenterX, textBaselineY, mTextPaint)
        canvas.restore()
    }

    /**
     * 绘制背景边框，并返回边框的Rect，供text计算位置使用
     *
     * @return
     */
    @SuppressLint("UseCompatLoadingForDrawables")
    private fun drawTagRect(canvas: Canvas, x: Float, y: Int, paint: Paint): Rect {
        val fontMetrics = paint.fontMetricsInt
        val fontHeight = fontMetrics.descent - fontMetrics.ascent
        val top = y + fontMetrics.ascent + (fontHeight - height) / 2
        val rect = Rect(x.toInt() + leftMargin, top, (x + leftMargin + width).toInt(), top + height)
        //如果有自定义背景，则忽略stroke。
        if (background != 0) {
            val drawable = mContext.resources.getDrawable(background)
            drawable.bounds = rect
            drawable.draw(canvas)
        } else {
            paint.color = strokeColor
            paint.style = Paint.Style.STROKE
            paint.strokeWidth = strokeWidth
            paint.isAntiAlias = true
            val oval = RectF(rect)
            canvas.drawRoundRect(oval, radius, radius, paint)
        }
        return rect
    }
}